package base.thread_example.example01;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 银行柜台/ATM取款多线程演示
 *
 * 100个线程(50个ATM机,50个柜台)同时从一个银行账户取款
 */
public class BankDemo {

    public static void main(String[] args) {
        //开辟一个银行账户,存款金额1w元
        BankAccount bank = new BankAccount(10000);
        // 创建一个任务协议,每次取200元,如果每次取款金额不等,那么需要定义多个任务协议对象
        WithdrawTask runnable = new WithdrawTask(bank,200);

        // 开启100个线程,50个模拟柜台取款,50个模拟ATM取款.(取款总金额:100*200)
        for (int i = 0; i < 50; i++) {
            new Thread(runnable,"柜台"+i).start();

            new Thread(runnable,"--------------> ATM"+i).start();
        }
    }


}

/**
 * 取款线程任务
 */
class WithdrawTask implements Runnable{
    private BankAccount bank;//银行账户
    private int amount;//取款金额
    public WithdrawTask(BankAccount bank, int amount){
        this.bank = bank;
        this.amount = amount;
    }

    @Override
    public void run() {
        try {
            this.bank.withdraw(this.amount);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


/**
 * 模拟一个银行账号.
 */
class BankAccount{
    private final Logger log = LoggerFactory.getLogger(BankAccount.class);
    private int amount;//账号存款金额
    public BankAccount(int amount){
        this.amount = amount;
    }

    // 取款操作
    public synchronized int withdraw (int amount) throws InterruptedException {
        if(amount<0){//取款金额为负
            log.info("-1");
            return -1;
        }else if(this.amount<amount){//账户金额不足
            log.info("-2");
            return -2;
        }else{
            Thread.sleep(100);//模拟取款延时
            this.amount -= amount;
            log.info("剩余存款:{}",this.amount);
            return this.amount;
        }
    }
}
